水無瀬の部屋 > Programming > sample > tools > ctrl > lnkctrl > lnkctrl.cpp |
---|
1: //*********************************************************
2: // プロジェクト: LinkLabel
3: // ファイル名: lnkctrl.cpp
4: //*********************************************************
5: #include <ctrl/lnkctrl/lnkctrl.h> //
6: #include <header/tooldbg.h> // ASSERT(), VERIFY(),
7: #include <header/toolbase.h> //
8: #include <header/toolwind.h> //
9: #include <header/toolsys.h> //
10:
11:
12: //---------------------------------------------------------
13: // マクロ の 定義
14: //---------------------------------------------------------
15: #define PROP_ORIGINALPROC "LLPROP_ORIGINALPROC" // 元のウィンドウ関数
16: #define PROP_CONTROLSTATE "LLPROP_CONTROLSTATE" // フォーカス状態
17: #define PROP_FONT "LLPROP_FONT" // 下線フォント
18: #define PROP_CURSOR "LLPROP_CURSOR" // 指カーソル
19: #define LLSTATE_FOCUS ( 0x01 ) // フォーカス状態である
20: #define IDT_MOUSEOVER ( 1 ) //
21:
22:
23: //---------------------------------------------------------
24: // マクロ関数 の 定義
25: //---------------------------------------------------------
26: #define SIZE_T_TO_INT( u ) ((int)( u )) // _W64
27:
28:
29: //---------------------------------------------------------
30: // ファイルスコープ関数 の 宣言
31: //---------------------------------------------------------
32: static LRESULT LinkLabel_SendClickedMessage( HWND hWnd );
33: static LRESULT LinkLabel_SendMouseLeaveMessage( HWND hWnd );
34: static LRESULT LinkLabel_SendMouseMoveMessage( HWND hWnd, WPARAM wParam, LPARAM lParam );
35: static LRESULT CallOriginalProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
36: static LRESULT CALLBACK LinkLabelProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
37: static void CALLBACK TrackMouseTimerProc( HWND hWnd, UINT uMsg, UINT uID, DWORD dwTime );
38: static HFONT CreateLinkLabelFont( HWND hWnd );
39:
40:
41: //*********************************************************
42: // SubclassLinkLabelControl
43: //*********************************************************
44: bool
45: SubclassLinkLabelControl
46: (
47: HWND hWnd
48: )
49: {
50: // パラメタの仮定
51: ASSERT( IsValidWindow( hWnd ) );
52: ASSERT( !GetProp( hWnd, PROP_FONT ) ); // まだ何も無いはず
53:
54: //
55: HFONT hfntUnderline = CreateLinkLabelFont( hWnd );
56: if ( hfntUnderline )
57: {
58: //
59: HINSTANCE hInstance = GetModuleHandle( null );
60: HCURSOR hcurHand = CreateHandCursor( hInstance );
61: if ( hcurHand )
62: {
63: //
64: WNDPROC OriginalProc = SubclassWindow64( hWnd, LinkLabelProc );
65: VERIFY( SetProp( hWnd, PROP_ORIGINALPROC, OriginalProc ) );
66: VERIFY( SetProp( hWnd, PROP_CONTROLSTATE, 0 ) );
67: VERIFY( SetProp( hWnd, PROP_CURSOR, hcurHand ) );
68: VERIFY( SetProp( hWnd, PROP_FONT, hfntUnderline ) );
69: SetWindowFont( hWnd, hfntUnderline, true );
70: return true;
71: }
72: }
73:
74: VERIFY( DeleteFont( hfntUnderline ) );
75: return false;
76: }//SubclassLinkLabelControl
77:
78:
79: //******************************************************************************************************************
80: // private
81: //******************************************************************************************************************
82: static LRESULT OnLinkLabelDestroy( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
83: static LRESULT OnLinkLabelPaint( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
84: static LRESULT OnLinkLabelSetCursor( HWND hWnd, WPARAM wParam, LPARAM lParam );
85: static LRESULT OnLinkLabelHitTest( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
86: static LRESULT OnLinkLabelLeftButtonUp( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
87: static LRESULT OnLinkLabelLeftButtonDown( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
88: static LRESULT OnLinkLabelMouseMove( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
89: static LRESULT OnLinkLabelNotify( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
90: static LRESULT OnLinkLabelNotifyMouseMove( HWND hWnd, LPARAM lParam );
91: static LRESULT OnLinkLabelNotifyMouseLeave( HWND hWnd, LPARAM lParam );
92: //static LRESULT OnLinkLabelNotifyMouseLeave( HWND hWnd, WPARAM wParam, LPARAM lParam );
93:
94:
95: //*********************************************************
96: // LinkLabelProc
97: //*********************************************************
98: static
99: LRESULT
100: CALLBACK
101: LinkLabelProc
102: (
103: HWND hWnd,
104: UINT uMsg,
105: WPARAM wParam,
106: LPARAM lParam
107: )
108: {
109: // パラメタの仮定
110: ASSERT( IsValidWindow( hWnd ) );
111:
112: switch( uMsg )
113: {
114: case WM_DESTROY: return OnLinkLabelDestroy( hWnd, uMsg, wParam, lParam );
115: case WM_PAINT: return OnLinkLabelPaint( hWnd, uMsg, wParam, lParam );
116: case WM_SETCURSOR: return OnLinkLabelSetCursor( hWnd, wParam, lParam );
117: case WM_NOTIFY: return OnLinkLabelNotify( hWnd, uMsg, wParam, lParam );
118: case WM_NCHITTEST: return OnLinkLabelHitTest( hWnd, uMsg, wParam, lParam );
119: case WM_MOUSEMOVE: return OnLinkLabelMouseMove( hWnd, uMsg, wParam, lParam );
120: case WM_LBUTTONDOWN: return OnLinkLabelLeftButtonDown( hWnd, uMsg, wParam, lParam );
121: case WM_LBUTTONUP: return OnLinkLabelLeftButtonUp( hWnd, uMsg, wParam, lParam );
122: default: return CallOriginalProc( hWnd, uMsg, wParam, lParam );
123: }
124: }//LinkLabelProc
125:
126: //*********************************************************
127: // OnLinkLabelDestroy
128: //*********************************************************
129: static
130: LRESULT
131: OnLinkLabelDestroy
132: (
133: HWND hWnd,
134: UINT uMsg,
135: WPARAM wParam,
136: LPARAM lParam
137: )
138: {
139: // パラメタの仮定
140: ASSERT( IsValidWindow( hWnd ) );
141: ASSERT( WM_DESTROY == uMsg );
142:
143: // サブクラス化の解除
144: WNDPROC OriginalProc = (WNDPROC)GetProp( hWnd, PROP_ORIGINALPROC );
145: VERIFY( SubclassWindow64( hWnd, OriginalProc ) );
146: VERIFY( RemoveProp( hWnd, PROP_ORIGINALPROC ) );
147: RemoveProp( hWnd, PROP_CONTROLSTATE );
148:
149: // フォントの破棄
150: HFONT hFont = (HFONT)GetProp( hWnd, PROP_FONT );
151: VERIFY( RemoveProp( hWnd, PROP_FONT ) );
152: if ( hFont )
153: {
154: VERIFY( DeleteFont( hFont ) );
155: }
156:
157: // 指カーソルを破棄
158: HCURSOR hcurHand = (HCURSOR)GetProp( hWnd, PROP_CURSOR );
159: VERIFY( RemoveProp( hWnd, PROP_CURSOR ) );
160: if ( hcurHand )
161: {
162: VERIFY( DestroyCursor( hcurHand ) );
163: }
164:
165: return CallWindowProc( OriginalProc, hWnd, uMsg, wParam, lParam );
166: }//OnLinkLabelDestroy
167:
168: //*********************************************************
169: // OnLinkLabelPaint
170: // クリック時の強調処理をするため
171: //*********************************************************
172: static
173: LRESULT
174: OnLinkLabelPaint
175: (
176: HWND hWnd,
177: UINT _unuse( uMsg ),
178: WPARAM ,
179: LPARAM
180: )
181: {
182: // パラメタの仮定
183: ASSERT( IsValidWindow( hWnd ) );
184: ASSERT( WM_PAINT == uMsg );
185:
186: PAINTSTRUCT ps;
187: BeginPaint( hWnd, &ps );
188: if ( ps.hdc )
189: {
190: //
191: const int nSaveDC = SaveDC( ps.hdc );
192:
193: // 前回の枠線消去
194: RECT rcClient;
195: VERIFY( GetClientRect( hWnd, &rcClient ) );
196: HBRUSH hbrBtnFace = GetSysColorBrush( COLOR_BTNFACE );
197: FillRect( ps.hdc, &rcClient, hbrBtnFace );
198:
199: // クリック時の枠線表示
200: const int state = (int)(INT_PTR)GetProp( hWnd, PROP_CONTROLSTATE );
201: if ( (hWnd == GetCapture()) && (LLSTATE_FOCUS == (LLSTATE_FOCUS & state)) )
202: {
203: // クリック時の枠線表示
204: RECT rcClient;
205: VERIFY( GetClientRect( hWnd, &rcClient ) );
206: HBRUSH hbrFrame = GetStockBrush( GRAY_BRUSH );
207: VERIFY( FrameRect( ps.hdc, &rcClient, hbrFrame ) );
208: }
209:
210: //
211: char *text = AllocWindowText( hWnd );
212: if ( text )
213: {
214: const int state = (int)(INT_PTR)GetProp( hWnd, PROP_CONTROLSTATE );
215: SetTextColor( ps.hdc, ((LLSTATE_FOCUS == (LLSTATE_FOCUS & state)) ? RGB(0xFF,0,0) : RGB(0,0,0xFF)) );
216:
217: //
218: HFONT hFont = GetWindowFont( hWnd );
219: if ( hFont )
220: {
221: SelectFont( ps.hdc, hFont );
222: SetBkMode( ps.hdc, TRANSPARENT );
223: VERIFY( TextOut
224: (
225: ps.hdc,
226: 0,
227: 0,
228: text,
229: SIZE_T_TO_INT( strlen( text ) )
230: ) );
231: }
232:
233: //
234: free( text );
235: }
236:
237: //
238: VERIFY( RestoreDC( ps.hdc, nSaveDC ) );
239: }
240: VERIFY( EndPaint( hWnd, &ps ) );
241:
242: return 0L; // CallOriginalProc( hWnd, uMsg, wParam, lParam );
243: }//OnLinkLabelPaint
244:
245: //*********************************************************
246: // OnLinkLabelSetCursor - WM_SETCURSOR
247: // カーソルが移動するたびに呼び出される。
248: // カーソルを変更する場合は 真 を返す。
249: // HWND wParam …… ウィンドウのハンドル
250: // LOWORD(lParam) …… HITTEST コード。
251: // HTCLIENT, HTCAPTION, HTMENU, ...
252: // HIWORD(lParam) …… ??? Value of the high-order word of lParam. Specifies the identifier of the mouse message.
253: //*********************************************************
254: static
255: LRESULT
256: OnLinkLabelSetCursor
257: (
258: HWND hWnd,
259: WPARAM _unuse( wParam ),
260: LPARAM _unuse( lParam )
261: )
262: {
263: // パラメタの仮定
264: ASSERT( IsValidWindow( hWnd ) );
265: ASSERT( IsValidSetCursorMessageParam( wParam, lParam ) );
266:
267: // カーソルを [手] にする
268: HCURSOR hcurHand = (HCURSOR)GetProp( hWnd, PROP_CURSOR );
269: if ( hcurHand )
270: {
271: SetCursor( hcurHand );
272: }
273:
274: return MAKELONG( true, 0 );
275: }//OnLinkLabelSetCursor
276:
277: //*********************************************************
278: // OnLinkLabelMouseMove
279: //*********************************************************
280: static
281: LRESULT
282: OnLinkLabelMouseMove
283: (
284: HWND hWnd,
285: UINT uMsg,
286: WPARAM wParam,
287: LPARAM lParam
288: )
289: {
290: // パラメタの仮定
291: ASSERT( IsValidWindow( hWnd ) );
292: ASSERT( WM_MOUSEMOVE == uMsg );
293:
294: if ( CursorInClient( hWnd ) )
295: {
296: VERIFY( IDT_MOUSEOVER == SetTimer( hWnd, IDT_MOUSEOVER, 0, TrackMouseTimerProc ) );
297: LinkLabel_SendMouseMoveMessage( hWnd, wParam, lParam );
298: }
299:
300: return CallOriginalProc( hWnd, uMsg, wParam, lParam );
301: }//OnLinkLabelMouseMove
302:
303: //*********************************************************
304: // OnLinkLabelHitTest
305: //*********************************************************
306: static
307: LRESULT
308: OnLinkLabelHitTest
309: (
310: HWND hWnd,
311: UINT uMsg,
312: WPARAM wParam,
313: LPARAM lParam
314: )
315: {
316: // パラメタの仮定
317: ASSERT( IsValidWindow( hWnd ) );
318: ASSERT( WM_NCHITTEST == uMsg );
319:
320: //
321: if ( CursorInClient( hWnd ) )
322: {
323: return HTCLIENT;
324: }
325:
326: return CallOriginalProc( hWnd, uMsg, wParam, lParam );
327: }//OnLinkLabelHitTest
328:
329: //*********************************************************
330: // OnLinkLabelLeftButtonDown
331: //*********************************************************
332: static
333: LRESULT
334: OnLinkLabelLeftButtonDown
335: (
336: HWND hWnd,
337: UINT uMsg,
338: WPARAM wParam,
339: LPARAM lParam
340: )
341: {
342: // パラメタの仮定
343: ASSERT( IsValidWindow( hWnd ) );
344: ASSERT( WM_LBUTTONDOWN == uMsg );
345: ASSERT( hWnd != GetCapture() );
346:
347: //
348: SetCapture( hWnd );
349: VERIFY( InvalidateWindow( hWnd, false ) );
350: return CallOriginalProc( hWnd, uMsg, wParam, lParam );
351: }//OnLinkLabelLeftButtonDown
352:
353: //*********************************************************
354: // OnLinkLabelLeftButtonUp
355: //*********************************************************
356: static
357: LRESULT
358: OnLinkLabelLeftButtonUp
359: (
360: HWND hWnd,
361: UINT uMsg,
362: WPARAM wParam,
363: LPARAM lParam
364: )
365: {
366: // パラメタの仮定
367: ASSERT( IsValidWindow( hWnd ) );
368: ASSERT( WM_LBUTTONUP == uMsg );
369:
370: // 通常時
371: if ( hWnd != GetCapture() )
372: return CallOriginalProc( hWnd, uMsg, wParam, lParam );
373:
374: //
375: ReleaseCapture();
376: if ( CursorInClient( hWnd ) )
377: {
378: LinkLabel_SendClickedMessage( hWnd );
379: }
380: return CallOriginalProc( hWnd, uMsg, wParam, lParam );
381: }//OnLinkLabelLeftButtonUp
382:
383:
384: //******************************************************************************************************************
385: // reflect
386: //******************************************************************************************************************
387: //*********************************************************
388: // OnLinkLabelNotify - WM_NOTIFY
389: // 子ウィンドウから通知メッセージを受け取った。
390: // 返値の意味は通知メッセージの種類による。
391: // int wParam …… メッセージを通知してきたウィンドウの識別子
392: // NMHDR *lParam …… 通知メッセージ構造体へのポインタ
393: //*********************************************************
394: static
395: LRESULT
396: OnLinkLabelNotify
397: (
398: HWND hWnd,
399: UINT uMsg,
400: WPARAM wParam,
401: LPARAM lParam
402: )
403: {
404: // パラメタの仮定
405: ASSERT( IsValidWindow( hWnd ) );
406: ASSERT( IsValidPtr( (NMLINKLABEL *)lParam, sizeof( NMLINKLABEL ) ) );
407: ASSERT( IsWindowNotifyMessageParam( hWnd, lParam ) );
408: ASSERT( wParam == (UINT)GetDlgCtrlID( hWnd ) );
409: ASSERT( WM_NOTIFY == uMsg );
410:
411: const UINT uNotifyCode = GetNotifyMessageNotifyCode( lParam );
412: switch( uNotifyCode )
413: {
414: // case LLN_CLICKED: return OnLinkLabelNotifyClicked( hWnd, uMsg, wParam, lParam );
415: case LLN_MOUSELEAVE: return OnLinkLabelNotifyMouseLeave( hWnd, lParam );
416: case LLN_MOUSEMOVE: return OnLinkLabelNotifyMouseMove( hWnd, lParam );
417: default: return CallOriginalProc( hWnd, uMsg, wParam, lParam );
418: }
419: }//OnLinkLabelNotify
420:
421: //*********************************************************
422: // OnLinkLabelNotifyMouseLeave
423: //*********************************************************
424: static
425: LRESULT
426: OnLinkLabelNotifyMouseLeave
427: (
428: HWND hWnd,
429: LPARAM _unuse( lParam )
430: )
431: {
432: // パラメタの仮定
433: ASSERT( IsValidWindow( hWnd ) );
434: ASSERT( IsValidPtr( (NMLINKLABEL *)lParam, sizeof( NMLINKLABEL ) ) );
435: ASSERT( IsWindowNotifyMessageParam( hWnd, lParam ) );
436: ASSERT( LLN_MOUSELEAVE == GetNotifyMessageNotifyCode( lParam ) );
437:
438: SetProp( hWnd, PROP_CONTROLSTATE, (HANDLE)0 );
439: VERIFY( InvalidateWindow( hWnd, false ) );
440: return 0L;
441: }//OnLinkLabelNotifyMouseLeave
442:
443: //*********************************************************
444: // OnLinkLabelNotifyMouseMove
445: //*********************************************************
446: static
447: LRESULT
448: OnLinkLabelNotifyMouseMove
449: (
450: HWND hWnd,
451: LPARAM _unuse( lParam )
452: )
453: {
454: // パラメタの仮定
455: ASSERT( IsValidWindow( hWnd ) );
456: ASSERT( IsValidPtr( (NMLINKLABEL *)lParam, sizeof( NMLINKLABEL ) ) );
457: ASSERT( IsWindowNotifyMessageParam( hWnd, lParam ) );
458: ASSERT( LLN_MOUSEMOVE == GetNotifyMessageNotifyCode( lParam ) );
459:
460: if ( CursorInClient( hWnd ) )
461: {
462: SetProp( hWnd, PROP_CONTROLSTATE, (HANDLE)LLSTATE_FOCUS );
463: }
464:
465: VERIFY( InvalidateWindow( hWnd, false ) );
466: return 0L;
467: }//OnLinkLabelNotifyMouseMove
468:
469:
470: //******************************************************************************************************************
471: // message
472: //******************************************************************************************************************
473: //*********************************************************
474: // LinkLabel_SendClickedMessage
475: //*********************************************************
476: static
477: LRESULT
478: LinkLabel_SendClickedMessage
479: (
480: HWND hWnd
481: )
482: {
483: // パラメタの仮定
484: ASSERT( IsValidWindow( hWnd ) );
485:
486: NMLINKLABEL nmll;
487: memzero( &nmll, sizeof( nmll ) );
488: VERIFY( MakeNotifyStruct( &nmll.hdr, hWnd, LLN_CLICKED ) );
489: HWND hParent = GetParent( hWnd );
490: return SendMessage( hParent, WM_NOTIFY, nmll.hdr.idFrom, (LPARAM)&nmll );
491: }//LinkLabel_SendClickedMessage
492:
493: //*********************************************************
494: // LinkLabel_SendMouseLeaveMessage
495: //*********************************************************
496: static
497: LRESULT
498: LinkLabel_SendMouseLeaveMessage
499: (
500: HWND hWnd
501: )
502: {
503: // パラメタの仮定
504: ASSERT( IsValidWindow( hWnd ) );
505:
506: NMLINKLABEL nmll;
507: memzero( &nmll, sizeof( nmll ) );
508: VERIFY( MakeNotifyStruct( &nmll.hdr, hWnd, LLN_MOUSELEAVE ) );
509: HWND hParent = GetParent( hWnd );
510: return SendMessage( hParent, WM_NOTIFY, nmll.hdr.idFrom, (LPARAM)&nmll );
511: }//LinkLabel_SendMouseLeaveMessage
512:
513: //*********************************************************
514: // LinkLabel_SendMouseMoveMessage
515: //*********************************************************
516: static
517: LRESULT
518: LinkLabel_SendMouseMoveMessage
519: (
520: HWND hWnd,
521: WPARAM wParam,
522: LPARAM lParam
523: )
524: {
525: // パラメタの仮定
526: ASSERT( IsValidWindow( hWnd ) );
527:
528: NMLINKLABEL nmll;
529: memzero( &nmll, sizeof( nmll ) );
530: VERIFY( MakeNotifyStruct( &nmll.hdr, hWnd, LLN_MOUSEMOVE ) );
531: nmll.wParam = wParam;
532: nmll.lParam = lParam;
533: HWND hParent = GetParent( hWnd );
534: return SendMessage( hParent, WM_NOTIFY, nmll.hdr.idFrom, (LPARAM)&nmll );
535: }//LinkLabel_SendMouseLeaveMessage
536:
537:
538: //******************************************************************************************************************
539: // callback
540: //******************************************************************************************************************
541: //*********************************************************
542: // TrackMouseTimerProc
543: //*********************************************************
544: static
545: void
546: CALLBACK
547: TrackMouseTimerProc
548: (
549: HWND hWnd,
550: UINT _unuse( uMsg ),
551: UINT uID,
552: DWORD
553: )
554: {
555: // パラメタの仮定
556: ASSERT( IsValidWindow( hWnd ) );
557: ASSERT( IDT_MOUSEOVER == uID );
558: ASSERT( WM_TIMER == uMsg );
559:
560: if ( !CursorInClient( hWnd ) )
561: {
562: VERIFY( KillTimer( hWnd, uID ) );
563: LinkLabel_SendMouseLeaveMessage( hWnd );
564: }
565:
566: }//TrackMouseTimerProc
567:
568:
569: //******************************************************************************************************************
570: // util
571: //******************************************************************************************************************
572: //*********************************************************
573: // CallOriginalProc
574: //*********************************************************
575: static
576: LRESULT
577: CallOriginalProc
578: (
579: HWND hWnd,
580: UINT uMsg,
581: WPARAM wParam,
582: LPARAM lParam
583: )
584: {
585: // パラメタの仮定
586: ASSERT( IsValidWindow( hWnd ) );
587:
588: WNDPROC OriginalProc = (WNDPROC)GetProp( hWnd, PROP_ORIGINALPROC );
589: return CallWindowProc( OriginalProc, hWnd, uMsg, wParam, lParam );
590: }//CallOriginalProc
591:
592: //*********************************************************
593: // CreateLinkLabelFont
594: //*********************************************************
595: static
596: HFONT
597: CreateLinkLabelFont
598: (
599: HWND hWnd
600: )
601: {
602: // パラメタの仮定
603: ASSERT( IsValidWindow( hWnd ) );
604:
605: //
606: LOGFONT lf;
607: if ( !GetWindowLogFont( hWnd, &lf ) )
608: return false;
609:
610: //
611: lf.lfUnderline = true;
612:
613: return CreateFontIndirect( &lf );
614: }//SubclassLinkLabelControl
615:
616:
617: //** end **
参照:
水無瀬の部屋 > sample > tools > ctrl > lnkctrl > lnkctrl.cpp |
---|
このページは cpp2web が出力しました。
水無瀬 優 postmaster@katsura-kotonoha.sakura.ne.jp
http://katsura-kotonoha.sakura.ne.jp/prog/code/tools/ctrl/lnkctrl/lnkctrl_cpp.shtml